/*
 *  Copyright 2009 Jan-Kees van Andel.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.jkva.jsf.components.nonvalidatingcommand;

import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UIInput;
import javax.faces.event.FacesEvent;
import java.util.List;

/**
 * This class contains all kind of useful methods,
 * that are used by both components
 */
public final class Util {

    /**
     * Utility class.
     */
    private Util() {
        throw new AssertionError("Utility class");
    }

    /**
     * Implementation method, called by the queueEvent method in both components.
     *
     * @param event The event.
     * @param self The calling component.
     */
    static void handleQueueEvent(FacesEvent event, UIComponent self) {
        // Only handle your own events.
        if (event.getComponent() == self) {
            // Look for the parent form.
            UIForm form = findParentForm(self);

            // And make sure there are no required fields in that form.
            setAllRequiredFieldsToNotRequired(form);
        }
    }

    /**
     * Find and return the nearest parent component that is a UIForm.
     *
     * @param component The component from where the searching goes upwards.
     * @return The nearest UIForm.
     */
    private static UIForm findParentForm(UIComponent component) {
        UIComponent parent = component.getParent();
        while (parent != null && !(parent instanceof UIForm)) {
            parent = parent.getParent();
        }
        if (parent instanceof UIForm) {
            return (UIForm) parent;
        } else {
            throw new AssertionError("No parent form found");
        }
    }

    /**
     * Implementation method, used to find all required
     * UIInput children in the given component and set
     * required to false.
     *
     * @param component The parent component. Usually a UIForm.
     */
    private static void setAllRequiredFieldsToNotRequired(UIComponent component) {
        List<UIComponent> children = component.getChildren();
        for (UIComponent child : children) {
            if (child instanceof UIInput) {
                UIInput input = (UIInput) child;
                if (input.isRequired()) {
                    // Set required to false and register input to be restored.
                    input.setRequired(false);
                    RestoreRequiredPhaseListener.inputsToRestore.get().add(input);
                }

            }
            setAllRequiredFieldsToNotRequired(child);
        }
    }

}
